﻿using System;
using System.Windows;
using Box2DX.Dynamics;
using System.Windows.Threading;
using System.Diagnostics;

namespace Expression.Samples.Physics.Behaviors
{
	/*
	public abstract class JointBehavior<T> : PhysicsBehavior where T : Joint
	{
		private T joint;
		private Body hostBody;
		private Body anchorBody;

		public static readonly DependencyProperty AnchorElementProperty = DependencyProperty.Register(
			"AnchorElement", 
			typeof(FrameworkElement), 
			typeof(JointBehavior<T>), 
			new PropertyMetadata(
				new PropertyChangedCallback(AnchorElementChanged)));

		public static readonly DependencyProperty CollideConnectedProperty = DependencyProperty.Register(
			"CollideConnected",
			typeof(bool),
			typeof(JointBehavior<T>),
			new PropertyMetadata(
				new PropertyChangedCallback(CollideConnectedChanged)));


		public FrameworkElement AnchorElement
		{
			get { return (FrameworkElement)this.GetValue(AnchorElementProperty); }
			set { this.SetValue(AnchorElementProperty, value); }
		}

		private static void AnchorElementChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
		{
			JointBehavior<T> jointBehavior = (JointBehavior<T>)obj;
			jointBehavior.RefreshJoint();
		}

		public bool CollideConnected
		{
			get { return (bool)this.GetValue(CollideConnectedProperty); }
			set { this.SetValue(CollideConnectedProperty, value); }
		}

		private static void CollideConnectedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
		{
			JointBehavior<T> jointBehavior = (JointBehavior<T>)obj;
			jointBehavior.RefreshJoint();
		}

		protected T Joint
		{
			get { return this.joint; }
		}

		protected Body HostBody
		{
			get
			{
				if (hostBody == null && this.Host != null)
				{
					this.hostBody = this.GetBody(this.Host);
				}
				return hostBody;
			}
		}

		protected Body AnchorBody
		{
			get
			{
				if (anchorBody == null && this.AnchorElement != null)
				{
					this.anchorBody = this.GetBody(this.AnchorElement);
				}
				return anchorBody;
			}
		}

		private Body GetBody(DependencyObject obj)
		{
			b.BehaviorCollection behaviors = b.Interactions.GetBehaviors(obj);
			foreach (b.Behavior behavior in behaviors)
			{
				BodyBehavior bodyBehavior = behavior as BodyBehavior;
				if (bodyBehavior != null)
				{
					return bodyBehavior.Body;
				}
			}
			return null;
		}

		protected override void OnHostChanged(DependencyObject oldHost, DependencyObject newHost)
		{
			FrameworkElement newHostElement = newHost as FrameworkElement;
			base.OnHostChanged(oldHost, newHost);
			if (this.PendingHostLoad)
			{
				this.PendingHostLoad = false;
				FrameworkElement oldHostElement = (FrameworkElement)oldHost;
				oldHostElement.Loaded -= HostElementLoaded;
			}

			this.DestroyJoint();

			this.hostBody = null;

			// create new joint
			if (newHostElement != null)
			{
				if (newHostElement.IsLoaded)
				{
					this.CreateJoint();
				}
				else
				{
					this.PendingHostLoad = true;
					newHostElement.Loaded += new RoutedEventHandler(HostElementLoaded);
				}
			}
		}

		private bool PendingHostLoad
		{
			get;
			set;
		}

		private void HostElementLoaded(object sender, RoutedEventArgs e)
		{
			this.PendingHostLoad = false;
			this.Host.Loaded -= new RoutedEventHandler(HostElementLoaded);
			this.Host.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback((object o) =>
			{
				this.CreateJoint();
				return null;
			}), null);
		}

		protected void RefreshJoint()
		{
			this.DestroyJoint();
			this.CreateJoint();
		}

		private void DestroyJoint()
		{
			if (this.joint != null)
			{
				this.Simulator.World.DestroyJoint(this.joint);
				this.joint = null;
			}
		}

		private void CreateJoint()
		{
			JointDef jointDef = this.InitializeJoint();
			if (jointDef != null && this.joint == null)
			{
				jointDef.CollideConnected = this.CollideConnected;
				this.joint = (T)this.Simulator.World.CreateJoint(jointDef);
			}
		}

		protected abstract JointDef InitializeJoint();
	}*/
}
